package com.mornstar.econvent.auth.config;

import com.mornstar.econvent.auth.handle.EcoAuthenticationEntryPoint;
import com.mornstar.econvent.auth.handle.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.ArrayList;
import java.util.List;

//@Configuration
//@EnableWebSecurity
public class SecureConfiguration {
    //@Autowired
    private UserDetailsService userDetailsService;

    /**
     * 认证失败处理类
     */
   // @Autowired
    private EcoAuthenticationEntryPoint unauthorizedHandler;

    /**
     * 配置资源相关端点，通用的过滤器链，用于处理整个应用程序的安全配置
     *
     * @param httpSecurity httpSecurity
     *
     * @return {@link SecurityFilterChain }
     * @throws Exception 异常
     */
    //@Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                .formLogin(Customizer.withDefaults())
                .httpBasic(Customizer.withDefaults())
                .csrf(csrf -> csrf.disable())
                .logout(logout -> logout.disable()) //禁用登出页面
                .headers((headersCustomizer) -> { // 禁用HTTP响应标头
                    headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin());
                })
               // .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))// 基于token，所以不需要session
                .authorizeHttpRequests(requests -> {
                    //permitAllUrl.getUrls().forEach(url -> requests.requestMatchers().permitAll());
                    // 对于登录login 注册register 验证码captchaImage 允许匿名访问
                    requests.requestMatchers(
                            "/oauth/captcha",
                            "/oauth/getSmsCode",
                            "/token/**"
                            ).permitAll()
                            .anyRequest()
                            .authenticated();
                })
                // 添加Logout filter
                .logout(logout -> logout.logoutUrl("/logout"))
                // 添加JWT filter
                .authenticationProvider(authenticationProvider())
                // 加我们自定义的过滤器，替代UsernamePasswordAuthenticationFilter
                //.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class)
                .build();
    }

//    @Bean
//    public DaoAuthenticationProvider daoAuthenticationProvider() {
//        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
//        provider.setUserDetailsService(null);
//        provider.setPasswordEncoder(null);
//        return provider;
//    }

    //@Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

   // @Bean
    public UserDetailsService userDetailsService() {
        // 调用 JwtUserDetailService实例执行实际校验
        return username -> userDetailsService.loadUserByUsername(username);
    }

    /**
     * 调用loadUserByUsername获得UserDetail信息，在AbstractUserDetailsAuthenticationProvider里执行用户状态检查
     *
     * @return
     */
    //@Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        // DaoAuthenticationProvider 从自定义的 userDetailsService.loadUserByUsername 方法获取UserDetails
        authProvider.setUserDetailsService(userDetailsService());
        // 设置密码编辑器
        authProvider.setPasswordEncoder(passwordEncoder());

        return authProvider;
    }

    /**
     * 可以扩展配置多个认证提供者
     *
     * @param config
     * @return
     * @throws Exception
     */
//    @Bean
//    public AuthenticationManager authenticationManager(HttpSecurity http, PasswordEncoder passwordEncoder,
//             CustomDaoAuthenticationProvider customDaoAuthenticationProvider,
//             LdapAuthenticationProvider ldapAuthenticationProvider) {
//        List<AuthenticationProvider> providers = new ArrayList<>();
//        providers.add(customDaoAuthenticationProvider);
//        providers.add(ldapAuthenticationProvider);
//        return new ProviderManager(providers);
//    }

//    @Bean
//    public JwtAuthenticationFilter authenticationJwtTokenFilter() {
//        return new JwtAuthenticationFilter(null);
//    }

    /**
     * 配置全局静态资源免验证登录
     *
     * **/
    //@Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring()
                        .requestMatchers(
                                "/swagger-ui.html",
                                "/webjars/**",
                                "/swagger-resources/**",
                                "/v2/api-docs",
                                "/attach/**",
                                "/tmp/attach/**"
                        );
    }
}
